package top.byfree.jbyan.saber.handler

import cn.dev33.satoken.exception.SaTokenException
import jakarta.validation.ConstraintViolation
import jakarta.validation.ConstraintViolationException
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.validation.BindException
import org.springframework.validation.FieldError
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.RestControllerAdvice
import top.byfree.jbyan.saber.common.R
import top.byfree.jbyan.saber.common.fail
import top.byfree.jbyan.saber.exception.AuthException
import top.byfree.jbyan.saber.exception.SaberServiceException
import java.util.function.Consumer

/**
 * @author jbyan
 * @since 22/12/2023
 */
@RestControllerAdvice
class GlobalExceptionHandler {

    private val log: Logger = LoggerFactory.getLogger(GlobalExceptionHandler::class.java)


    @ExceptionHandler(SaTokenException::class)
    fun notLoginExceptionHandler(e: SaTokenException): R<Unit> {
        return fail(code = 401, message = e.message.toString())
    }

    @ExceptionHandler(AuthException::class)
    fun notLoginExceptionHandler(e: AuthException): R<Unit> {
        return fail(code = 401, message = e.message.toString())
    }

    @ExceptionHandler(SaberServiceException::class)
    fun serviceExceptionHandler(e: SaberServiceException): R<Unit> {
        return fail(code = 500, message = e.message ?: "系统异常")
    }

    @ExceptionHandler(ConstraintViolationException::class)
    fun validExceptionHandler(e: ConstraintViolationException): R<Map<String, String>> {
        val constraintViolations = e.constraintViolations
        val map: MutableMap<String, String> = HashMap()
        // key字段分割 -> importMd.userId
        constraintViolations.forEach(Consumer { i: ConstraintViolation<*> ->
            map[i.propertyPath.toString().split("\\.".toRegex()).dropLastWhile { it.isEmpty() }
                .toTypedArray()[1]] = i.message
        })
        log.warn("数据校验异常：$map")
        return fail(message = "数据校验异常", data =  map)
    }

    @ExceptionHandler(BindException::class)
    fun validExceptionHandler(e: BindException): R<Map<String, String>> {
        val fieldErrors = e.fieldErrors
        val map: MutableMap<String, String> = HashMap()
        fieldErrors.forEach(Consumer { i: FieldError ->
            map[i.field] = i.defaultMessage!!
        })
        log.warn("数据校验异常：$map")
        return fail(message = "数据校验异常", data = map)
    }


}